package ru.compft.common.dao.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import ru.compft.common.dao.RoleDao;
import ru.compft.common.data.AppRole;
import ru.compft.common.utils.CommonUtils;
import ru.compft.common.utils.GlobalConstants;
import ru.compft.common.utils.StringConverter;

import java.io.*;
import java.util.LinkedList;
import java.util.List;

/**
 * User: VVasiliev
 * Date: 14.06.12
 * Time: 14:08
 * Пример реализации функциональности работы с ролями пользователя
 * Нужен для демонстрационной версии
 */
@Repository
public class ExampleRoleDaoImpl implements RoleDao {
    private static final Logger logger = LoggerFactory.getLogger(ExampleRoleDaoImpl.class);

    private String ROLES_CSV = "/roles.csv";

    @Override
    public List<AppRole> getAllRoles() {
        return readFromFile();
    }

    @Override
    public List<AppRole> getRoles(int from, int count) {
        return CommonUtils.getPartOfList(from, count, readFromFile());
    }

    @Override
    public int countAllRoles() {
        return readFromFile().size();
    }

    public void addRole(AppRole appRole) {
    }

    @Override
    public AppRole getRoleById(Long roleId) {
        final List<AppRole> appRoleList = readFromFile();
        if (!CollectionUtils.isEmpty(appRoleList)) {
            for (AppRole appRole : appRoleList) {
                if (appRole.getId().equals(roleId))
                    return appRole;
            }
        }
        return null;
    }

    /**
     * Получение роли по коду
     *
     * @param code
     * @return
     */
    @Override
    public AppRole getRoleByCode(String code) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public Long generateId() {
        return System.currentTimeMillis();
    }

    @Override
    public AppRole update(AppRole newRole) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    /**
     * Сохраняем новую роль
     *
     * @param role
     * @return
     */
    @Override
    public AppRole persist(AppRole role) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    /**
     * Удаляем роль
     *
     * @param role
     * @return
     */
    @Override
    public Boolean delete(AppRole role) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    /**
     * Считываем данные из файла
     *
     * @return
     */
    private List<AppRole> readFromFile() {
        final List<AppRole> result = new LinkedList<AppRole>();
        BufferedReader br = null;

        try {
            final String fullPath = System.getProperty(GlobalConstants.USER_DIR_PROP_NAME) + GlobalConstants.CACHE_DATA + ROLES_CSV;
            final File resourceFile = new File(fullPath);
            if (!resourceFile.exists())
                throw new FileNotFoundException("File " + fullPath + " not found.");

            br = new BufferedReader(new InputStreamReader(
                    new FileInputStream(resourceFile), GlobalConstants.DEFAULT_ENCODING));

            String strLine;
            boolean firstString = true;

            //Read File Line By Line
            while ((strLine = br.readLine()) != null) {
                // пропускаем первую строку, т.к. там лежат имена колонок
                if (firstString) {
                    firstString = false;
                    continue;
                }

                strLine = strLine.replaceAll(GlobalConstants.DOUBLE_QUOTA, GlobalConstants.EMPTY_STRING);

                final String[] fieldArray = strLine.split(GlobalConstants.DOT_COMMA);
                if (fieldArray.length != 4)
                    throw new Exception("Field array more or less than 4 records");

                final Long id = Long.valueOf(fieldArray[0].trim());
                final String code = fieldArray[1].trim();
                final String name = fieldArray[2].trim();
                final String description = fieldArray[3].trim();

                // создаем роль
                final AppRole role = new AppRole();
                role.setId(id);
                role.setCode(code);
                role.setName(name);
                role.setDescription(description);
                result.add(role);
            }
        } catch (IOException e) {
            logger.error("Can't read from file " + ROLES_CSV, e);
        } catch (Exception e) {
            logger.error("Error while read from file " + ROLES_CSV, e);
        } finally {
            if (br != null)
                try {
                    br.close();
                } catch (IOException e) {
                    // ignore
                }
        }

        return result;
    }

    /**
     * Записываем данные в файл
     *
     * @return
     */
    private boolean writeToFile(AppRole appRole) {
        BufferedWriter out = null;

        try {
            final String fullPath = System.getProperty(GlobalConstants.USER_DIR_PROP_NAME) + GlobalConstants.CACHE_DATA + ROLES_CSV;
            final File resourceFile = new File(fullPath);
            if (!resourceFile.exists())
                throw new FileNotFoundException("File " + fullPath + " not found.");

            // создаем строку вида: "ID";"CODE";"NAME";"DESCRIPTION"
            final String csvRecord = StringConverter.createCsvRecord(new String[]{appRole.getId().toString(), appRole.getCode(), appRole.getName(), appRole.getDescription()});

            out = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(resourceFile, true), GlobalConstants.DEFAULT_ENCODING));

            out.write(csvRecord);
            out.flush();

            return true;
        } catch (IOException e) {
            logger.error("Can't write to file " + ROLES_CSV, e);
        } catch (Exception e) {
            logger.error("Error while write to file " + ROLES_CSV, e);
        } finally {
            if (out != null)
                try {
                    out.close();
                } catch (IOException e) {
                    // ignore
                }
        }
        return false;
    }
}
